package cn.agiledata.bank.audit.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.springframework.orm.hibernate3.HibernateTemplate;

import cn.agiledata.bank.audit.logic.AuditStatus;
import cn.agiledata.bank.hibernateBean.AuditOperandType;
import cn.agiledata.bank.hibernateBean.AuditOperation;
import cn.agiledata.bank.hibernateBean.HistoryAuditOperation;
import cn.agiledata.bank.hibernateBean.RecentAuditOperation;
import cn.agiledata.bank.hibernateBean.UserInfo;
import com.vnv.infrastructure.logic.IPBHibernate3BaseMgr;

/**
 * 
 * @author 马贤波
 * 
 */
public class AuditOperationDaoImpl extends IPBHibernate3BaseMgr implements
        IAuditOperationDao {

    public RecentAuditOperation getRecentAuditOperation(
            AuditOperandType auditOperandType, long auditOperandId) {
        String hql = "from RecentAuditOperation rao where rao.auditRule.auditOperandType=? and rao.auditOperandId=?";
        HibernateTemplate ht = this.getHibernateTemplate();
        int maxResults = ht.getMaxResults();
        ht.setMaxResults(1);
        List resultList = ht.find(hql, new Object[] { auditOperandType,
                new Long(auditOperandId) });
        ht.setMaxResults(maxResults);
        return resultList.size() == 0 ? null
                : (RecentAuditOperation) resultList.get(0);
    }

    public HistoryAuditOperation[] getHistoryAuditOperations(
            AuditOperandType auditOperandType, long auditOperandId) {
        String hql = "from HistoryAuditOperation hao where hao.auditRule.auditOperandType=? and hao.auditOperandId=? order by hao.sequenceNo";
        List resultList = this.getHibernateTemplate().find(hql,
                new Object[] { auditOperandType, new Long(auditOperandId) });
        return (HistoryAuditOperation[]) resultList
                .toArray(new HistoryAuditOperation[0]);
    }

    private List queryPagingByNamedParams(String hql, Map params,
            int beginIndex, int maxTotal) {
        Query query = getSession().createQuery(hql);
        if (beginIndex > 0 && maxTotal > 0) {
            query.setFirstResult(beginIndex - 1); // query的索引从0开始
            query.setMaxResults(maxTotal);
        }
        for (Iterator it = params.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            Object value = entry.getValue();
            if (value instanceof List) {
                query.setParameterList((String) entry.getKey(), (List) value);
            } else {
                query.setParameter((String) entry.getKey(), value);
            }
        }
        return query.list();
    }

    public long getHistoryAuditOperationsTotal(
            AuditOperandType auditOperandType, AuditStatus[] postStatuses,
            UserInfo[] users, Date beginAuditTime, Date endAuditTime) {
        String hql = "select count(hao) from HistoryAuditOperation hao where hao.auditRule.auditOperandType=:aot ";
        Map params = new HashMap();
        params.put("aot", auditOperandType);
        if (postStatuses != null && postStatuses.length > 0) {
            hql += " and hao.postStatus in (:ps) ";
            List postStatusList = new ArrayList();
            for (int i = 0; i < postStatuses.length; i++) {
                int status = postStatuses[i].getValue();
                postStatusList.add(new Integer(status));
            }
            params.put("ps", postStatusList);
        }
        if (users != null && users.length > 0) {
            hql += " and hao.updateUser in (:users) ";
            List userList = new ArrayList();
            for (int i = 0; i < users.length; i++) {
                userList.add(users[i].getId().toString());
            }
            params.put("users", userList);
        }
        if (beginAuditTime != null) {
            hql += " and hao.updateTime>=:bat ";
            params.put("bat", beginAuditTime);
        }
        if (endAuditTime != null) {
            hql += " and hao.updateTime<=:eat ";
            params.put("eat", endAuditTime);
        }
        hql += " order by hao.auditOperandId, hao.sequenceNo";
        List resultList = queryPagingByNamedParams(hql, params, 0, 0);
        return ((Long) resultList.get(0)).longValue();
    }

    public HistoryAuditOperation[] getHistoryAuditOperations(
            AuditOperandType auditOperandType, AuditStatus[] postStatuses,
            UserInfo[] users, Date beginAuditTime, Date endAuditTime,
            int beginIndex, int maxTotal) {
        String hql = "from HistoryAuditOperation hao where hao.auditRule.auditOperandType=:aot ";
        Map params = new HashMap();
        params.put("aot", auditOperandType);
        if (postStatuses != null && postStatuses.length > 0) {
            hql += " and hao.postStatus in (:ps) ";
            List postStatusList = new ArrayList();
            for (int i = 0; i < postStatuses.length; i++) {
                int status = postStatuses[i].getValue();
                postStatusList.add(new Integer(status));
            }
            params.put("ps", postStatusList);
        }
        if (users != null && users.length > 0) {
            hql += " and hao.updateUser in (:users) ";
            List userList = new ArrayList();
            for (int i = 0; i < users.length; i++) {
                userList.add(users[i].getId().toString());
            }
            params.put("users", userList);
        }
        if (beginAuditTime != null) {
            hql += " and hao.updateTime>=:bat ";
            params.put("bat", beginAuditTime);
        }
        if (endAuditTime != null) {
            hql += " and hao.updateTime<=:eat ";
            params.put("eat", endAuditTime);
        }
        hql += " order by hao.auditOperandId, hao.sequenceNo";
        List resultList = queryPagingByNamedParams(hql, params, beginIndex,
                maxTotal);
        return (HistoryAuditOperation[]) resultList
                .toArray(new HistoryAuditOperation[0]);
    }

    public RecentAuditOperation[] getAuditingRecentAuditOperations(
            AuditOperandType[] auditOperandTypes, int beginIndex, int maxTotal) {
        String hql = "from RecentAuditOperation rao where rao.auditRule.auditOperandType in (:aot) ";
        Map params = new HashMap();
        List aotList = new ArrayList();
        for (int i = 0; i < auditOperandTypes.length; i++) {
            aotList.add(auditOperandTypes[i]);
        }
        params.put("aot", aotList);
        hql += "and rao.postStatus not in (:nps) ";
        List nonPostStatus = new ArrayList();
        nonPostStatus.add(new Integer(AuditStatus.STATUS_UNKNOWN.getValue()));
        nonPostStatus.add(new Integer(AuditStatus.STATUS_CANCEL.getValue()));
        nonPostStatus.add(new Integer(AuditStatus.STATUS_PRIMARY.getValue()));
        nonPostStatus.add(new Integer(AuditStatus.STATUS_REJECTED.getValue()));
        nonPostStatus.add(new Integer(AuditStatus.STATUS_FINAL.getValue()));
        params.put("nps", nonPostStatus);
        hql += "order by rao.updateTime desc, rao.auditOperandId desc";
        List resultList = queryPagingByNamedParams(hql, params, beginIndex,
                maxTotal);
        return (RecentAuditOperation[]) resultList
                .toArray(new RecentAuditOperation[0]);
    }

    public void saveOrUpdateAuditOperation(AuditOperation auditOperation) {
        this.getHibernateTemplate().saveOrUpdate(auditOperation);
        this.getHibernateTemplate().flush();
    }

}
